-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[shared_preferences] update List<String> encode/decode #8335
base: main
Are you sure you want to change the base?
Conversation
@stuartmorgan ready for review here as well |
...ndroid/src/main/java/io/flutter/plugins/sharedpreferences/LegacySharedPreferencesPlugin.java
Show resolved
Hide resolved
...ndroid/src/main/java/io/flutter/plugins/sharedpreferences/LegacySharedPreferencesPlugin.java
Show resolved
Hide resolved
private @NonNull Map<String, Object> getAllPrefs( | ||
@NonNull String prefix, @Nullable Set<String> allowList) throws RuntimeException { | ||
Map<String, ?> allPrefs = preferences.getAll(); | ||
Map<String, Object> filteredPrefs = new HashMap<>(); | ||
for (String key : allPrefs.keySet()) { | ||
if (key.startsWith(prefix) && (allowList == null || allowList.contains(key))) { | ||
filteredPrefs.put(key, transformPref(key, allPrefs.get(key))); | ||
filteredPrefs.put(key, transformPref(key, Objects.requireNonNull(allPrefs.get(key)))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was requireNonNull needed here? Also this code is getting a bit difficult to parse. (A loop with a conditional that sets some transformed filtered data) Consider breaking parts out into methods or adding comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a change suggested by a warning I was getting in Android Studio. Since the method being called requires nonnull arguments and getting a value from a map doesn't programmatically guarantee a value. In this context, there would always be a value though.
@@ -148,32 +141,14 @@ public void onDetachedFromEngine(@NonNull FlutterPlugin.FlutterPluginBinding bin | |||
private Object transformPref(@NonNull String key, @NonNull Object value) { | |||
if (value instanceof String) { | |||
String stringValue = (String) value; | |||
if (stringValue.startsWith(LIST_IDENTIFIER)) { | |||
if (stringValue.startsWith(JSON_LIST_IDENTIFIER)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is where having the keys be similar starts to be important. That said from reading the code the reader does not know the keys are overlapping and it would seem safe in code review to swap the order of these if statements.
Consider making the keys independent so that you are not relying on the contents of the keys. If that is too much code change then consider making a "LIST_PREFIX" that can be checked so that it is at least clear in code what the relationship is.
If you want further reading see
https://www.16elt.com/2024/09/25/first-book-of-byte-sized-tech/
I think the first example explains the principal I am applying.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider making the keys independent so that you are not relying on the contents of the keys.
This is something Tarrin and I had discussed offline; making it a prefix avoids this being a potentially (very unlikely, but still possible) breaking change, by using our already-reserved space.
I would strongly prefer we keep that, and adjust the code to make it explicit to readers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I can understand that fear and why it might fail. Thank you for being open to structuring the code differently so that the overlap is easier to follow for future maintainers.
...ndroid/src/main/java/io/flutter/plugins/sharedpreferences/LegacySharedPreferencesPlugin.java
Outdated
Show resolved
Hide resolved
...preferences/shared_preferences_android/example/integration_test/shared_preferences_test.dart
Outdated
Show resolved
Hide resolved
@@ -1,3 +1,9 @@ | |||
## 3.0.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the breaking changes required? if not consider fixing/mitigating the security issue independent of the breaking changes. It makes it more likely for them to be adopted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Breaking changes to shared_preferences
have the potential to be quite disruptive to the ecosystem; I would strongly prefer we keep the legacy type support around to making a breaking change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. I originally expected this change was going to end up being "technically" breaking due to the new prefix (before we discussed the prefix extension plan) so I wanted to wrap these long awaited breaking changes in as well. I'll revert them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Breaking changes to
shared_preferences
have the potential to be quite disruptive to the ecosystem; I would strongly prefer we keep the legacy type support around to making a breaking change.
Should I revert the error handling changes as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I revert the error handling changes as well?
I did this.
packages/shared_preferences/shared_preferences_android/lib/src/strings.dart
Show resolved
Hide resolved
packages/shared_preferences/shared_preferences_android/lib/src/shared_preferences_android.dart
Outdated
Show resolved
Hide resolved
@@ -39,20 +41,27 @@ class SharedPreferencesAndroid extends SharedPreferencesStorePlatform { | |||
Future<bool> setValue(String valueType, String key, Object value) async { | |||
switch (valueType) { | |||
case 'String': | |||
return _api.setString(key, value as String); | |||
value as String; | |||
if (value.startsWith(listPrefix) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this list grow? if so consider making a set of prefixes to check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't generally add types to shared_preferences
since anything that all platforms don't support ends up with unpleasant complexity like the List<String>
mess we are currently dealing with.
@@ -1,3 +1,9 @@ | |||
## 3.0.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Breaking changes to shared_preferences
have the potential to be quite disruptive to the ecosystem; I would strongly prefer we keep the legacy type support around to making a breaking change.
...roid/android/src/main/kotlin/io/flutter/plugins/sharedpreferences/SharedPreferencesPlugin.kt
Outdated
Show resolved
Hide resolved
@@ -39,20 +41,27 @@ class SharedPreferencesAndroid extends SharedPreferencesStorePlatform { | |||
Future<bool> setValue(String valueType, String key, Object value) async { | |||
switch (valueType) { | |||
case 'String': | |||
return _api.setString(key, value as String); | |||
value as String; | |||
if (value.startsWith(listPrefix) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't generally add types to shared_preferences
since anything that all platforms don't support ends up with unpleasant complexity like the List<String>
mess we are currently dealing with.
Follow up to #8187
Updates Android
List<String>
encoding/decoding to use JSON to avoid potential future breakages from restricted list types.